gusucode.com > VC++ EMF图片浏览器(可读emf、wmf、emz、wmz、png……等)-源码程序 > VC++ EMF图片浏览器(可读emf、wmf、emz、wmz、png……等)-源码程序/code/Src/Client/scwinlib/SCGDIUtils.cpp
//Download by http://www.NewXing.com /* * This file is part of the EMFexplorer projet. * Copyright (C) 2004 Smith Charles. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. * * Extension: for commercial use, apply the Equity Public License, which * adds to the normal terms of the GLPL a condition of donation to the author. * If you are interested in support for this source code, * contact Smith Charles <smith.charles@free.fr> for more information. */ #include "stdafx.h" #include "SCGDIUtils.h" #include "MSDib.h" #include "SCGenInclude.h" #include SC_INC_GENLIB(SCGenMath.h) #include SC_INC_GENLIB(SCGenDefs.h) #include <afxext.h> // printdlg #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif /// /// Calculates the palette size in bytes. If the info. block /// is of the BITMAPCOREHEADER type, the number of colors is /// multiplied by 3 to give the palette size, otherwise the /// number of colors is multiplied by 4. /// WORD SCColorTableSize (LPBITMAPINFOHEADER lpbih) { if (NEW_DIB_FORMAT(lpbih)) { if (lpbih->biCompression == BI_BITFIELDS) /* Remember that 16/32bpp dibs can still have a color table */ return (sizeof(DWORD) * 3) + (DIBNumColors(lpbih) * sizeof (RGBQUAD)); else return (DIBNumColors(lpbih) * sizeof(RGBQUAD)); } else return (DIBNumColors(lpbih) * sizeof(RGBTRIPLE)); } /// /// Create a 24bpp RGB copy of a palette bitmap. /// hRefDC must contain the realized palette from where colors are taken. /// HBITMAP SCConvertPalDIBToRGB(HDC hRefDC, LPCBYTE lpSrcBits, LPCBITMAPINFO lpSrcBmi) { INT iWidth = lpSrcBmi->bmiHeader.biWidth; INT iHeight = abs(lpSrcBmi->bmiHeader.biHeight); BITMAPINFO bmiTarget; bmiTarget.bmiHeader.biSize = sizeof( BITMAPINFOHEADER ); bmiTarget.bmiHeader.biWidth = iWidth; bmiTarget.bmiHeader.biHeight = lpSrcBmi->bmiHeader.biHeight; bmiTarget.bmiHeader.biPlanes = 1; bmiTarget.bmiHeader.biBitCount = 24; bmiTarget.bmiHeader.biCompression = BI_RGB; bmiTarget.bmiHeader.biSizeImage = 0; bmiTarget.bmiHeader.biXPelsPerMeter = 0; bmiTarget.bmiHeader.biYPelsPerMeter = 0; bmiTarget.bmiHeader.biClrUsed = 0; bmiTarget.bmiHeader.biClrImportant = 0; VOID* lpTargetBits; HBITMAP hTargetBitmap = CreateDIBSection(hRefDC, &bmiTarget, DIB_RGB_COLORS, &lpTargetBits, NULL, 0 ); HDC hTargetDC = CreateCompatibleDC( hRefDC ); HBITMAP hOldTargetBitmap = (HBITMAP)SelectObject( hTargetDC, hTargetBitmap ); INT iRes = SetDIBitsToDevice(hTargetDC, 0, 0, iWidth, iHeight, 0, 0, 0, iHeight, lpSrcBits, lpSrcBmi, DIB_PAL_COLORS); ASSERT(iRes); GdiFlush(); // let GDI finish before we access the bits // Cleanup SelectObject(hTargetDC, hOldTargetBitmap); DeleteDC(hTargetDC); return hTargetBitmap; } void SCNormalizeRect(LPRECT prc) { ASSERT(prc); if (prc->right < prc->left) SMC_ISWAP(prc->right, prc->left); if (prc->bottom < prc->top) SMC_ISWAP(prc->bottom, prc->top); } void SCGetNormalizedRect(LPRECT pRcDest, LPCRECT pRcSrc) { ASSERT(pRcDest && pRcSrc); if (pRcSrc->right < pRcSrc->left) { pRcDest->left = pRcSrc->right; pRcDest->right = pRcSrc->left; } else { pRcDest->left = pRcSrc->left; pRcDest->right = pRcSrc->right; } if (pRcSrc->bottom < pRcSrc->top) { pRcDest->top = pRcSrc->bottom; pRcDest->bottom = pRcSrc->top; } else { pRcDest->top = pRcSrc->top; pRcDest->bottom = pRcSrc->bottom; } } /// /// Draw a frame and right-bottom shadow /// void SCDrawFrameAndShadow(CDC *pDC, int x, int y, int cx, int cy, int iShWdt, COLORREF BkColor, BOOL bFrame/*=TRUE*/) { ASSERT(pDC); int iXRight = x + cx; int iYBottom = y + cy; // Shadow if (iShWdt) { CBrush *pBrush = CBrush::FromHandle((HBRUSH)GetStockObject(BLACK_BRUSH)); // Right band CRect rc(iXRight, y + 2, iXRight + iShWdt + 1, iYBottom + iShWdt + 1); pDC->FillRect(&rc, pBrush); // Bottom band rc.left = x + 2; rc.top = iYBottom; pDC->FillRect(&rc, pBrush); } // Frame if (bFrame) { CRect rc(x, y, iXRight, iYBottom); InflateRect(&rc, 1, 1); CBrush *pBrush = CBrush::FromHandle((HBRUSH)GetStockObject(NULL_BRUSH)); CBrush *pOldBrush = pDC->SelectObject(pBrush); CPen Pen; Pen.CreatePen(PS_SOLID, 0, BkColor); CPen* pOldPen = pDC->SelectObject(&Pen); int iOldRop2 = pDC->SetROP2(R2_NOTCOPYPEN); pDC->Rectangle(&rc); // Clean up pDC->SetROP2(iOldRop2); pDC->SelectObject(pOldPen); pDC->SelectObject(pOldBrush); Pen.DeleteObject(); } } /// /// Comptutes character extents by hand (panic function) /// BOOL SCComputeTextExtentPointW(HDC hAttDC, LPCWSTR pwString, INT iCount, INT *pCharDx, SIZE &TextSize) { ASSERT(pCharDx); if (!pCharDx) return FALSE; pCharDx[0] = 0; SIZE tmpSize; TextSize.cy = 0; for (INT nInd = 0; (nInd < iCount); nInd++) { GetTextExtentPoint32W(hAttDC, pwString, nInd+1, &tmpSize); pCharDx[nInd] = tmpSize.cx; if (TextSize.cy<tmpSize.cy) TextSize.cy = tmpSize.cy; } TextSize.cx = tmpSize.cx; return TRUE; } /// /// Returns an array containing the width of each character in a text. /// The lpCharWidths buffer must be large enough to hold iCount ints. /// BOOL SCGetTextCharWidthsW(HDC hDC, LPCWSTR pwString, INT iCount, INT *lpCharWidths) { ASSERT(lpCharWidths); if (!lpCharWidths) return FALSE; // We want the horizontal extents (otherwise, for a vertical font, // GetTextExtentExPoint would return character heights in lpCharWidths) HFONT hFont = NULL; HFONT hHorizFont = NULL; if (hFont = (HFONT)GetCurrentObject(hDC, OBJ_FONT)) { LOGFONT LogFont; ::GetObject(hFont, sizeof(LogFont), &LogFont); if (LogFont.lfEscapement) { LogFont.lfEscapement = 0; LogFont.lfOrientation = 0; hHorizFont = (HFONT)CreateFontIndirect(&LogFont); if (hHorizFont) SelectObject(hDC, hHorizFont); } } // SetTextJustification(hDC, 0, 0); // Compute extents SIZE Size; INT bRes = GetTextExtentExPointW(hDC, pwString, iCount, 0, NULL, lpCharWidths, &Size); // Do not ASSERT: some fonts support characters with 0 width (A+B+C) //ASSERT(Size.cx && Size.cy && *lpCharWidths); if (0 == bRes) { DWORD dwGLE = GetLastError(); // panic if (!SCComputeTextExtentPointW(hDC, pwString, iCount, lpCharWidths, Size)) { // panic panic if (hHorizFont) { SelectObject(hDC, hFont); DeleteObject(hHorizFont); } return FALSE; } } // Convert extents to char widths for (INT i = iCount - 1; i>0; i--) lpCharWidths[i] -= lpCharWidths[i-1]; if (hHorizFont) { SelectObject(hDC, hFont); DeleteObject(hHorizFont); } return TRUE; } BOOL SCGetTextCharWidthsHImW(HDC hDC, LPCWSTR pwString, INT iCount, INT *lpCharWidths, float fScaleX, float fScaleY) { ASSERT(lpCharWidths); if (!lpCharWidths) return FALSE; BOOL bResult = TRUE; // We want the horizontal extents (otherwise, for a vertical font, // GetTextExtentExPoint would return character heights in lpCharWidths) HFONT hFont = NULL; HFONT hHorizFont = NULL; if (hFont = (HFONT)GetCurrentObject(hDC, OBJ_FONT)) { LOGFONT LogFont; ::GetObject(hFont, sizeof(LogFont), &LogFont); if (LogFont.lfEscapement) { LogFont.lfEscapement = 0; LogFont.lfOrientation = 0; hHorizFont = (HFONT)CreateFontIndirect(&LogFont); if (hHorizFont) SelectObject(hDC, hHorizFont); } } // SetTextJustification(hDC, 0, 0); // Compute extents SIZE Size; INT bRes = GetTextExtentExPointW(hDC, pwString, iCount, 0, NULL, lpCharWidths, &Size); ASSERT(Size.cx && Size.cy && *lpCharWidths); if (0 == bRes) { DWORD dwGLE = GetLastError(); // panic bResult = SCComputeTextExtentPointW(hDC, pwString, iCount, lpCharWidths, Size); } // Convert extents to char widths if (bResult) { for (INT i = iCount - 1; i>0; i--) lpCharWidths[i] -= lpCharWidths[i-1]; // text aspect ratio float fRatio = (float)(fabs(fScaleY)/fabs(fScaleX)); for (INT j = 0; j<iCount; j++) lpCharWidths[j] = (int)(lpCharWidths[j]*fRatio); } if (hHorizFont) { SelectObject(hDC, hFont); DeleteObject(hHorizFont); } return bResult; } /// /// Expand a monochrome DIB bitmap to and array of lWidth x lHeight pixels. /// If lWidth x lHeight is larger than the monochrome bitmap, the latter is replicated. /// BYTE* SCExpandMask(LONG lWidth, LONG lHeight, LONG lxMask, LONG lyMask, LPCBYTE pBitsMask, LPCBITMAPINFO pBmiMask, DWORD dwUsageMask, BOOL bTopDown/*=FALSE*/) { ASSERT(pBitsMask && pBmiMask); ASSERT(dwUsageMask==2/*DIB_PAL_INDICES*/); ASSERT(lWidth>0 && lHeight>0); ASSERT(1==pBmiMask->bmiHeader.biBitCount && 1==pBmiMask->bmiHeader.biPlanes); ASSERT(pBmiMask->bmiHeader.biHeight>0); BYTE* pResult = new BYTE[lWidth*lHeight]; BYTE* pDest = pResult; // Note: the mask is always a 1-bit DIB. And: // "1-bit DIBs are stored using each bit as an index into the color table. // The most significant bit is the leftmost pixel." DWORD dwBytesPerLine = WIDTHBYTES(pBmiMask->bmiHeader.biWidth); DWORD dwStartScan = lyMask * dwBytesPerLine; // Theoretical first useful bit inside the first useful byte on scanline BYTE bStartBitNumber = (BYTE)(lxMask % 8); // Theoretical max useful bit inside the last useful byte on scanline BYTE bMaxBitNumber = (BYTE)(pBmiMask->bmiHeader.biWidth % 8); DWORD dwMaxByteOnLine = pBmiMask->bmiHeader.biWidth >> 3; BYTE* pXStart = (BYTE*)pBitsMask + dwStartScan; BYTE* pYLimit = (BYTE*)pBitsMask + (pBmiMask->bmiHeader.biHeight-1) * dwBytesPerLine; if (bTopDown) {// Make the layout for a top-down bitmap for (LONG y=0; (y<lHeight); y++) { BYTE* pXLimit = pXStart + dwMaxByteOnLine; // inclusive end of scanline BYTE* pX = pXStart + (lxMask >> 3); // byte on the scanline BYTE bBitNumber = bStartBitNumber; // theoretical bit inside the byte for (LONG x=0; (x<lWidth); x++, pDest++) { // the most significant bit is the leftmost pixel; so get the complement // of the theoretical bit number if (*pX & (1<<(7 - bBitNumber))) *pDest = 1; else *pDest = 0; bBitNumber++; if (pX==pXLimit) {// last useful bit on last useful byte reached: restart if (bBitNumber>=bMaxBitNumber) { pX = pXStart + (lxMask >> 3); bBitNumber = bStartBitNumber; } } else if (bBitNumber>7) {// no more bits available in this byte: go to next byte ++pX; if (pX>pXLimit) {// can't go next: back to start pX = pXStart + (lxMask >> 3); bBitNumber = bStartBitNumber; } else bBitNumber = 0; // first bit of next byte } } // next scan pXStart += dwBytesPerLine; if (pXStart>pYLimit) {// restart to begining of mask pXStart = (BYTE*)pBitsMask + dwStartScan; } } } else {// Make the layout for a bottom-up bitmap. BYTE* pDestRow = pResult + lWidth*lHeight; for (LONG y=0; (y<lHeight); y++) { BYTE* pXLimit = pXStart + dwMaxByteOnLine; // inclusive end of scanline BYTE* pX = pXStart + (lxMask >> 3); // byte on the scanline BYTE bBitNumber = bStartBitNumber; // theoretical bit inside the byte pDestRow -= lWidth; pDest = pDestRow; for (LONG x=0; (x<lWidth); x++, pDest++) { // the most significant bit is the leftmost pixel; so get the complement // of the theoretical bit number if (*pX & (1<<(7 - bBitNumber))) *pDest = 1; else *pDest = 0; bBitNumber++; if (pX==pXLimit) {// last useful byte reached if (bBitNumber>=bMaxBitNumber) {// last useful bit on last useful byte reached: restart pX = pXStart + (lxMask >> 3); bBitNumber = bStartBitNumber; } } else if (bBitNumber>7) {// no more bits available in this byte: go to next byte if (++pX>pXLimit) {// can't go next: back to start pX = pXStart + (lxMask >> 3); bBitNumber = bStartBitNumber; } else bBitNumber = 0; // first bit of next byte } } // next scan pXStart += dwBytesPerLine; if (pXStart>pYLimit) {// restart to begining of mask pXStart = (BYTE*)pBitsMask + dwStartScan; } } } return pResult; } /// /// Create a transparent bitmap from a DIB bitmap and masking information. /// Note: the mask array must conatain exactly /// pSrcBmi->bmiHeader.biWidth x pSrcBmi->bmiHeader.biHeight pixels /// HBITMAP SCBuildAlphaBitmap(LPCBYTE pSrcBits, LPCBITMAPINFO pSrcBmi, DWORD dwSrcUsage, BYTE* pMask, BOOL bFlip/*=FALSE*/) { // Create a packed-DIB header. DWORD dwSize = sizeof(BITMAPINFOHEADER); BYTE* pBytes = new BYTE[dwSize]; ASSERT(pBytes); if (!pBytes) return NULL; // Finish Initialize header. int width = pSrcBmi->bmiHeader.biWidth; int height = abs(pSrcBmi->bmiHeader.biHeight); BITMAPINFOHEADER* pHdr = &((BITMAPINFO*)pBytes)->bmiHeader; pHdr->biSize = sizeof(BITMAPINFOHEADER); pHdr->biWidth = width; pHdr->biHeight = (bFlip) ? -pSrcBmi->bmiHeader.biHeight : pSrcBmi->bmiHeader.biHeight; pHdr->biPlanes = 1; pHdr->biBitCount = 32; pHdr->biCompression = BI_RGB; pHdr->biClrUsed = 0; // just set the rest to 0 pHdr->biSizeImage = 0; pHdr->biXPelsPerMeter = 0; pHdr->biYPelsPerMeter = 0; pHdr->biClrImportant = 0; pHdr->biSizeImage = width * height * 4; // Create the surface. HDC hRefDC = GetDC( NULL ); LPVOID pBits; HBITMAP hbm = CreateDIBSection(hRefDC, (BITMAPINFO*)pBytes, DIB_RGB_COLORS, &pBits, NULL, 0); ASSERT(hbm); if (hbm) { // Copy the source bits. Note: // "GDI automatically inverts the image during the Set and Get operations." // 'invert' means 'flip upside_down/bottom_up'. SetDIBits(hRefDC, hbm, 0, height, (CONST VOID *)pSrcBits, (BITMAPINFO*)pSrcBmi, dwSrcUsage); // Merge alpha information (mask) GdiFlush(); BYTE* pAlpha = pMask; UINT32 *puiVal = (UINT32 *)pBits; UINT32 *pStop = puiVal + height*width; if (bFlip) {// top-down DIB while (puiVal < pStop) { if (1==*pAlpha++) {// opaque // A value of 1 in the mask indicates opaque pixel. *puiVal |= 0xff000000; } // A value of 0 in the mask indicates fully transparent pixel. else *puiVal &= 0x00ffffff; puiVal++; } } else {// bottom-up DIB UINT32 *puiRow = pStop; BYTE *pAlphaRow = pMask + height*width; while (puiRow>pBits) { puiRow -= width; pAlphaRow -= width; puiVal = puiRow; pAlpha = pAlphaRow; for (LONG x=0; (x<width); x++) { if (1==*pAlpha++) *puiVal |= 0xff000000; else *puiVal &= 0x00ffffff; puiVal++; } } } } ReleaseDC( NULL, hRefDC ); delete [] pBytes; return(hbm); } BYTE SGGetMonoDIBPixel(LPBYTE pBits, DWORD dwWidth, DWORD dwHeight, DWORD x, DWORD y) { // Find the byte on which the scanline begins + (the byte containing the pixel) DWORD dwByteIndex = (dwHeight - y - 1) * WIDTHBYTES(dwWidth) + (x >> 3); // Which bit is it? BYTE bBitNumber = (BYTE)( 7 - (x % 8) ); return (pBits[dwByteIndex] & (1<<bBitNumber)); } /// /// Tell if hDC is a monochrome device. /// BOOL SCIsMonochromeDC(HDC hDC) { HBITMAP hBM = (HBITMAP)GetCurrentObject(hDC, OBJ_BITMAP); if (hBM) { BITMAP bm; GetObject(hBM, sizeof(bm), &bm); return (bm.bmBitsPixel==1 && bm.bmPlanes==1); } return FALSE; } /// /// Fill a two-color palette with current text/background colors of DC. /// (For monochrome brush color realization) /// void SCFillMonochromePalette(HDC hDC, PPALETTEENTRY palPalEntry) { ASSERT(palPalEntry); COLORREF crBkColor = GetBkColor(hDC); COLORREF crTextColor = GetTextColor(hDC); palPalEntry[0].peRed = GetRValue(crTextColor); palPalEntry[0].peGreen = GetGValue(crTextColor); palPalEntry[0].peBlue = GetBValue(crTextColor); palPalEntry[0].peFlags = 0; palPalEntry[1].peRed = GetRValue(crBkColor); palPalEntry[1].peGreen = GetGValue(crBkColor); palPalEntry[1].peBlue = GetBValue(crBkColor); palPalEntry[1].peFlags = 0; } /// /// Make the device dependent version of a DIB /// HBITMAP SCDIBtoMonochromeBitmap(HDC hDCRef, BITMAPINFO* pBmi, DWORD *pBitsDW) { ASSERT(pBmi); ASSERT(pBitsDW); ASSERT(hDCRef); // Attach a monochrome palette to the DIB specification, // and create a device-dependent bitmap HBITMAP hBm = NULL; DWORD dwSize = pBmi->bmiHeader.biSize + 2*sizeof(RGBQUAD); BITMAPINFO* pBmi2 = (BITMAPINFO*) new BYTE[dwSize]; memmove(pBmi2, pBmi, dwSize); HDC hMonoDC = CreateCompatibleDC(hDCRef); // must be monochrome ASSERT(hMonoDC); SCFillMonochromePalette(hDCRef, (PPALETTEENTRY)pBmi2->bmiColors); // May create resource leak, as we don't call DeleteObject on hBm hBm = CreateDIBitmap(hMonoDC, &pBmi2->bmiHeader, CBM_INIT, pBitsDW, pBmi2, DIB_RGB_COLORS); DeleteDC(hMonoDC); delete [] (BYTE*)pBmi2; return hBm; } ////////////////////////////////////////////////////////////////////// /// Font family substitution /// typedef struct tag_SCSysFont { TCHAR* szFacename; DWORD dwFamily; } SCSysFont, *PSCSysFont; // Vector and Raster fonts supposed to be on all systems SCSysFont s_szSysVRFonts[] = { _T("modern"), FF_MODERN, // Vector _T("roman"), FF_ROMAN, // Vector _T("script"), FF_DONTCARE, // Vector _T("courier"), FF_ROMAN, // Raster _T("fixedsys"), FF_SWISS, // Raster _T("ms sans serif"), FF_SWISS, // Raster _T("ms serif"), FF_ROMAN, // Raster _T("small fonts"), FF_SWISS, // Raster _T("symbol"), FF_DONTCARE, // Raster _T("system"), FF_SWISS, // Raster _T("terminal"), FF_SWISS // Raster }; // _T("arial"), FF_SWISS, // TrueType // _T("courier new"), FF_ROMAN, // TrueType // _T("symbol"), FF_DONTCARE,// TrueType // _T("times new roman"), FF_ROMAN, // TrueType // _T("wingdings"), FF_DONTCARE,// TrueType // _T("helv"), FF_SWISS, // _T("helvetica"), FF_SWISS, // _T("tms rmn"), FF_ROMAN, // dutch->times // bookman->times int s_lNbSysVRFonts = sizeof(s_szSysVRFonts)/sizeof(SCSysFont); DWORD SCFontFamilyApproximant(LPCTSTR lpszFacename) { TCHAR szName[LF_FACESIZE+1]; _tcsncpy(szName, lpszFacename, LF_FACESIZE); szName[LF_FACESIZE]=0; _tcslwr(szName); for (int i=0; (i<s_lNbSysVRFonts); i++) if (0==_tcscmp(s_szSysVRFonts[i].szFacename, szName)) return s_szSysVRFonts[i].dwFamily; return FF_DONTCARE; } inline DWORD SCFontFamilyApproximantA(LPCSTR lpszFacename) { return SCFontFamilyApproximant((TCHAR*)lpszFacename); } DWORD SCFontFamilyApproximantW(LPCWSTR lpwszFacename) { #ifdef _UNICODE return SCFontFamilyApproximant(lpwszFacename); #else char szFaceName[LF_FACESIZE]; WideCharToMultiByte(CP_ACP, 0, lpwszFacename, LF_FACESIZE, szFaceName, LF_FACESIZE, NULL, NULL); return SCFontFamilyApproximant((LPCSTR)szFaceName); #endif } BOOL SCIsIdentityXFORM(XFORM& rXForm) { return (rXForm.eM11==1.0 && rXForm.eM22==1.0 && rXForm.eM12==0.0 && rXForm.eM21==0.0 && rXForm.eDx==0.0 && rXForm.eDy==0.0); } HDC SCGetDefaultPrinterDC(HWND hwndOwner/*=NULL*/) { PRINTDLG pd; { pd.lStructSize = sizeof (PRINTDLG); BOOL bExistPrinter = (AfxGetApp()->GetPrinterDeviceDefaults(&pd)); #ifdef _DEBUG {// spying DEVMODE * pDevMode = (DEVMODE *)::GlobalLock(pd.hDevMode); ::GlobalUnlock(pd.hDevMode); } #endif pd.hwndOwner = hwndOwner; pd.hDevMode = (HANDLE)NULL; pd.hDevNames = (HANDLE)NULL; pd.nFromPage = 0; pd.nToPage = 0; pd.nMinPage = 0; pd.nMaxPage = 0; pd.nCopies = 0; pd.hInstance = (HINSTANCE)AfxGetApp()->m_hInstance; pd.Flags = PD_RETURNDEFAULT|PD_RETURNDC; pd.lpfnSetupHook = (LPSETUPHOOKPROC)(FARPROC)NULL; pd.lpSetupTemplateName = (LPTSTR)NULL; pd.lpfnPrintHook = (LPPRINTHOOKPROC)(FARPROC)NULL; pd.lpPrintTemplateName = (LPTSTR)NULL; if (bExistPrinter && (PrintDlg(&pd) == TRUE)) return pd.hDC; } return NULL; } //////////////////////////////////////////////////////////////////////////// // // Test stuff // void SCTestShadedRectangle(HDC hDC, LPCRECT pRect, int iMode) { ASSERT(hDC); ASSERT(pRect); TRIVERTEX vert[2] ; GRADIENT_RECT gRect; vert [0] .x = pRect->left; vert [0] .y = pRect->top; vert [0] .Red = 0x0000; vert [0] .Green = 0x0000; vert [0] .Blue = 0x0000; vert [0] .Alpha = 0x0000; vert [1] .x = pRect->right; vert [1] .y = pRect->bottom; vert [1] .Red = 0x0000; vert [1] .Green = 0x0000; vert [1] .Blue = 0xff00; vert [1] .Alpha = 0x0000; gRect.UpperLeft = 0; gRect.LowerRight = 1; GradientFill(hDC, vert, 2, &gRect, 1, iMode); } void SCTestShadedTriangle(HDC hDC, LPCRECT pRect) { ASSERT(hDC); ASSERT(pRect); TRIVERTEX vert[4]; GRADIENT_TRIANGLE gTri[2]; vert [0] .x = (pRect->left+pRect->right)/2; vert [0] .y = pRect->top; vert [0] .Red = 0x0000; vert [0] .Green = 0x0000; vert [0] .Blue = 0x0000; vert [0] .Alpha = 0x0000; vert [1] .x = pRect->right; vert [1] .y = (pRect->top+pRect->bottom)/2; vert [1] .Red = 0x0000; vert [1] .Green = 0x0000; vert [1] .Blue = 0xff00; vert [1] .Alpha = 0x0000; vert [2] .x = (pRect->left+pRect->right)/2; vert [2] .y = pRect->bottom; vert [2] .Red = 0xff00; vert [2] .Green = 0x0000; vert [2] .Blue = 0xff00; vert [2] .Alpha = 0x0000; vert [3] .x = pRect->left; vert [3] .y = (pRect->top+pRect->bottom)/2; vert [3] .Red = 0x0000; vert [3] .Green = 0xff00; vert [3] .Blue = 0xff00; vert [3] .Alpha = 0x0000; gTri[0].Vertex1 = 0; gTri[0].Vertex2 = 1; gTri[0].Vertex3 = 2; gTri[1].Vertex1 = 0; gTri[1].Vertex2 = 2; gTri[1].Vertex3 = 3; GradientFill(hDC, vert, 4, &gTri[0], 2, GRADIENT_FILL_TRIANGLE); } void SCEMFExplorerPaint(CDC* pDC, const CRect* pRect, LPCTSTR lpszMsgID/*=_T("")*/, LPCTSTR lpszMsgAction/*=_T("")*/) { ASSERT(pDC); ASSERT(pRect); SCTestShadedRectangle(pDC->m_hDC, pRect, GRADIENT_FILL_RECT_V); SCTestShadedTriangle(pDC->m_hDC, pRect); pDC->SetBkMode(TRANSPARENT); pDC->SetTextColor(RGB(255, 0, 255)); LOGFONT LogFont; memset(&LogFont, 0, sizeof(LogFont)); LogFont.lfHeight = -20; LogFont.lfWeight = FW_BOLD; LogFont.lfCharSet = ANSI_CHARSET; LogFont.lfOutPrecision = OUT_TT_PRECIS; LogFont.lfClipPrecision = CLIP_DEFAULT_PRECIS; LogFont.lfQuality = DEFAULT_QUALITY; LogFont.lfPitchAndFamily = FF_ROMAN|DEFAULT_PITCH; _tcscpy ((TCHAR*)LogFont.lfFaceName, _T("Times New Roman")); HFONT hFont = CreateFontIndirect(&LogFont); HFONT hOldFont = (HFONT)SelectObject(pDC->m_hDC, hFont); int iY = 0; CString strMsg = (lpszMsgID) ? lpszMsgID : _T(""); if (!strMsg.IsEmpty()) { CSize size = pDC->GetTextExtent(strMsg); iY = (pRect->Height() - 3*size.cy)/2; pDC->TextOut((pRect->Width() - size.cx)/2, iY, strMsg); iY += 2*size.cy; } strMsg = (lpszMsgAction) ? lpszMsgAction : _T(""); if (!strMsg.IsEmpty()) { CSize size = pDC->GetTextExtent(strMsg); if (!iY) iY = (pRect->Height() - 3*size.cy)/2; pDC->TextOut((pRect->Width() - size.cx)/2, iY, strMsg); } DeleteObject(SelectObject(pDC->m_hDC,hOldFont)); } ////////////////////////////////////////////////////////////////////////////